#!/usr/bin/env perl

BEGIN {
	push @INC,$ENV{CODEMGR_LIBS} if exists($ENV{CODEMGR_LIBS});
}

use warnings;
use English;
use Cwd;
use Data::Dumper;
use Getopt::Long;
use File::Basename;
use codemgr2 qw(logmsg warnmsg errormsg get_project remove_dir_path);

$ARG_version=0;
$ARG_verbose=0;
$ARG_tag=undef;
$ARG_preview=0;
$ARG_overwrite=0;
$ARG_tmpdir=undef;
$ARG_cfgfile="pkg/pkgconf";
$ARG_tp2bin=undef;
$ARG_project=undef;
$ARG_indir=undef;
$ARG_repos=undef;
$ARG_name=undef;

$_PRG=basename($0);
$_SPC=" " x length($_PRG);

if(substr($0,0,1) eq "." || substr($0,0,1) eq ".") {
	$BINPATH=dirname($0);
} else {
	$BINPATH="";
}

sub usage {
	print "
       $_PRG  --tag T             - Generate TP2 package based on tag
       $_SPC [--cfgfile C] [--verbose] [--tp2bin B] [--name N] [--indir D]
       $_SPC [--overwrite] [--repos D]
";
	exit(1);
}

sub get_dir_matches($$) {
my ($dir,$pat)=@_;
my ($dfd,@m);

	$pat =~ s/\./\\./g;
	$pat =~ s/\*/.*/g;

	opendir($dfd,$dir) or return();
	@m=grep {-f "$dir/$_" && /^$pat$/} readdir($dfd);
	closedir($dfd);
	return (@m);
}

#########################################################################
# Make use the PROJECTS_ROOT directory exists...			#
#########################################################################

if(!exists($ENV{PROJECTS_ROOT})) {
	errormsg("Required environment variable \"PROJECTS_ROOT\" is not set.",3);
}

$PROJECTS_ROOT=$ENV{PROJECTS_ROOT};

if(! -d $ENV{PROJECTS_ROOT}) {
	errormsg("\"PROJECTS_ROOT\" directory \"$PROJECTS_ROOT\" does not exist.",2);
}

if(!GetOptions(
	"V"		=> \$ARG_version,
	"preview"	=> \$ARG_preview,
	"overwrite"	=> \$ARG_overwrite,
	"verbose"	=> \$ARG_verbose,
	"tag=s"		=> \$ARG_tag,
	"project=s"	=> \$ARG_project,
	"tmpdir=s"	=> \$ARG_tmpdir,
	"indir=s"	=> \$ARG_indir,
	"repos=s"	=> \$ARG_repos,
	"tp2bin=s"	=> \$ARG_tp2bin,
	"cfgfile=s"	=> \$ARG_cfgfile,
	"name=s"	=> \$ARG_name,
	)) {
	usage;
}

if($ARG_version) {
	print "2\n";
	exit(0);
}

usage if !defined($ARG_tag);
usage if !defined($ARG_name);

if(!defined($ARG_cfgfile)) {
	$ARG_cfgfile="pkg/pkgconf";
	logmsg("Defaulted \"cfgfile\" to \"$ARG_cfgfile\".");
}

#########################################################################
# Load in the configuration details....					#
#########################################################################

if(!open($fd,$ARG_cfgfile)) {
	errormsg("Unable to read configuration file \"$ARG_cfgfile\" - aborting.");
	exit(1);
}

%cfginfo=();
while(<$fd>) {
	chomp;
	@F=split;
	next if ! /^[A-Z]/;
	$F[0] =~ s/:.*$//;
	$ck=$F[0];
	$ck="OS" if $ck eq "OSRELEASE";
	$cfginfo{$ck}=[] if !exists($cfginfo{$ck});
	s/^[A-Z_0-9]+:\s*//;
	if($ck eq "OS") {
		push @{$cfginfo{$ck}},lc($_);
	} else {
		push @{$cfginfo{$ck}},$_;
	}
}
close($fd);

$cfginfo{NAME}=[$ARG_name];

$PKG_NAME=$cfginfo{NAME}->[0];
if($::ARG_preview) {
	print Dumper(\%cfginfo);
}

#########################################################################
# Ok, if there is a build script then run it.				#
#########################################################################

if(exists($cfginfo{BUILD})) {
	foreach $sc (@{$cfginfo{BUILD}}) {
		if(-f $sc) {
			chmod 0555,$sc;
			logmsg("Executing build script: $sc");
			system($sc);
			$rc=$?>>8;
			if($rc) {
				warnmsg("Script $sc RC=$rc");
			}
		}
	}
}

if(!$ARG_preview) {
	$cfgfile2="/tmp/$PKG_NAME-$$";
	open($fd,">$cfgfile2");
} else {
	$fd=*STDOUT;
}

#########################################################################
# Now we generate the XML packaging file for tp2pkg.			#
#########################################################################

print $fd "<?xml version=\"1.0\" standalone=\"yes\"?>\n";
print $fd "<tp2package>\n";
print $fd "  <name>$PKG_NAME</name>\n";
print $fd "  <version>$ARG_tag</version>\n";

#########################################################################
# Do optional install scripts and os/architecture			#
#########################################################################

for $cc ("description","preinstall","postinstall","preremove","postremove","checkinstall",
		"os","architecture","description_file","readme_file","copyright_file",
		"license_file") {
	$cc2=uc($cc);
	print $fd "  <$cc>".$cfginfo{$cc2}->[0]."</$cc>\n" if exists($cfginfo{$cc2});
}

#########################################################################
# Do the DEPENDS_ON functionality.					#
#########################################################################

if(exists($cfginfo{DEPENDS_ON})) {
	print $fd "  <dependencies>\n";
	foreach $cpkg (@{$cfginfo{DEPENDS_ON}}) {
		@F=split(/,/,$cpkg);
		if(!exists($F[1])) {
			print $fd "    <pkg minver=\"0.0.1\">";
		} else {
			print $fd "    <pkg minver=\"$F[1]\">";
		}
		print $fd "$F[0]</pkg>\n";
	}
	print $fd "  </dependencies>\n";
}

print $fd "  <files>\n";
if(exists($cfginfo{DIR})) {
	#################################################################
	# Stuff all the dir entries into the file...			#
	#################################################################
	foreach $cdir (
		sort {	my (@c,@d); @c=split(/\s+/,$a); @d=split(/\s+/,$b);
			length($c[0]) <=> length($d[0]);
		} @{$cfginfo{DIR}}) {
		@F=split(/\s+/,$cdir);
		if(@F!=2) {
			errormsg("Malformed 'DIR:' line '$cdir' - aborting",1);
		}
		@F2=split(/,/,$F[1]);
		print $fd "    <dir";
		print $fd " owner=\"$F2[0]\"" if $F2[0] ne "";
		print $fd " group=\"$F2[1]\"" if $F2[1] ne "";
		print $fd " perms=\"$F2[2]\"" if $F2[2] ne "";
		print $fd ">$F[0]</dir>\n";
	}
}

if(exists($cfginfo{FILE})) {
	#################################################################
	# Stuff all the dir entries into the file...			#
	#################################################################
	foreach $cfile (
		sort {	my (@c,@d); @c=split(/\s+/,$a); @d=split(/\s+/,$b);
			length($c[0]) <=> length($d[0]);
		} @{$cfginfo{FILE}}) {
		@F=split(/\s+/,$cfile);
		if(@F!=2) {
			errormsg("Malformed 'DIR:' line '$cdir' - aborting",1);
		}
		@F2=split(/,/,$F[1]);
		$volatile=$configfile=0;
		if($F2[0] =~ /^volatile$/i) {
			$volatile=1;
			shift @F2;
		}
		if($F2[0] =~ /^configfile$/i) {
			$configfile=1;
			shift @F2;
		}
		@m=get_dir_matches(dirname($F[0]),basename($F[0]));
		foreach $ccfile (@m) {
			print $fd "    <file";
			print $fd " volatile=\"y\"" if $volatile;
			print $fd " configfile=\"y\"" if $configfile;
			print $fd " owner=\"$F2[1]\"" if $F2[1] ne "";
			print $fd " group=\"$F2[2]\"" if $F2[2] ne "";
			print $fd " perms=\"$F2[3]\"" if $F2[3] ne "";
			print $fd ">".dirname($F[0])."/$ccfile";
			print $fd "=$F2[0]/$ccfile" if $F2[0] ne "";
			print $fd "</file>\n";
		}
	}
}
print $fd "  </files>\n";
print $fd "</tp2package>\n";
close($fd);
if($ARG_preview) {
	exit(0);
}

#########################################################################
# Now the configuration has been written attempt to generate the	#
# package.								#
#########################################################################

$cmd="";
if(defined($ARG_tp2bin) && -d $ARG_tp2bin) {
	$cmd.="$ARG_tp2bin/";
} else {
	$cmd="$BINPATH/" if $BINPATH ne "";
}

$cmd.="tp2pkg --config $cfgfile2";
$cmd.=" --verbose" if $ARG_verbose;
$cmd.=" --overwrite" if $ARG_overwrite;
$cmd.=" --indir $ARG_indir" if $ARG_indir;
$cmd.=" --repos $ARG_repos" if $ARG_repos;

logmsg("");
logmsg("Building package using command:");
logmsg("$cmd");
logmsg("");
system("$cmd");
$rc=$?>>8;
if($rc) {
	unlink $cfgfile2;
	errormsg("Unable to build package $PKG_NAME!",1);
}
unlink $cfgfile2;
if(!$ARG_verbose) {
	$ARG_verbose=1;
	logmsg("Package $PKG_NAME built successfully.");
}
exit(0);
